//
//  ZLRuntimeViewController.m
//  ZLClient
//
//  Created by lizhu on 2017/6/26.
//  Copyright © 2017年 zhuli. All rights reserved.
//

#import "ZLRuntimeViewController.h"
#import "ZLRuntimeViewController+CategoryProperty.h"
#import "ZLModel.h"
#import "NSObject+ZLHook.h"
#import <objc/message.h>

@interface ZLRuntimeViewController ()

@end

@implementation ZLRuntimeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.categoryProperty=@"categoryProperty";
    NSLog(@"%@",self.categoryProperty);
    
    NSDictionary *dic = @{@"name":@"我爱NBA",
                          @"sex":@"男",
                          @"age":@25
                          };
    ZLModel *model = [ZLModel modelWithDict:dic];
    NSLog(@"name:%@  sex:%@  ",model.name,model.sex);

    //获取UIPageControl的私有属性和方法
    [self getAllIvar];
    
    //对私有变量的更改
    [self changePrivate];
    //获取所有的方法(包括私有的)
    [self getAllMethod];
    
    //动态添加方法
    // 默认model，没有实现eat方法，可以通过performSelector调用，但是会报错。
    // 动态添加方法就不会报错
    [model performSelector:@selector(eat)];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/
#pragma mark - 获取所有的属性(包括私有的)
- (void)getAllIvar {
    unsigned int count = 0;
    //Ivar：定义对象的实例变量，包括类型和名字。
    //获取所有的属性(包括私有的)
    Ivar *ivars= class_copyIvarList([UIPageControl class], &count);
    for (int i = 0; i < count; i++) {
        //取出成员变量
        Ivar ivar = ivars[i];
        
        NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
        NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
        NSLog(@"属性 --> %@ 和 %@",name,type);
        
    }
    free(ivars);
}
#pragma mark - 获取所有的方法(包括私有的)
- (void)getAllMethod {
    unsigned int count = 0;
    //获取所有的方法(包括私有的)
    Method *memberFuncs = class_copyMethodList([UIPageControl class], &count);
    for (int i = 0; i < count; i++) {
        
        SEL address = method_getName(memberFuncs[i]);
        NSString *methodName = [NSString stringWithCString:sel_getName(address) encoding:NSUTF8StringEncoding];
        
        NSLog(@"方法 : %@",methodName);
    }
    free(memberFuncs);
}

#pragma mark - 对私有变量的更改
- (void)changePrivate {
    ZLModel *onePerson = [[ZLModel alloc] init];
    NSLog(@"Person属性 == %@",[onePerson description]);
    
    unsigned  int count = 0;
    Ivar *members = class_copyIvarList([ZLModel class], &count);
    
    for (int i = 0; i < count; i++){
        Ivar var = members[i];
        const char *memberAddress = ivar_getName(var);
        const char *memberType = ivar_getTypeEncoding(var);
        NSLog(@"获取所有属性 = %s ; type = %s",memberAddress,memberType);
    }
    //对私有变量的更改
    Ivar m_address = members[3];
    object_setIvar(onePerson, m_address, @"上海");
    NSLog(@"对私有变量的(地址)进行更改 : %@",[onePerson description]);
    free(members);
}
@end
